﻿using soma.Helpers;
using soma.Models.Resources;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace soma.Services
{
    public abstract class Repository
    {
        protected const string CacheKeysTags = "TagsDictionary";
        protected abstract string CacheKeysResources { get; }
        protected HttpContext context;

        protected static Object locker = new Object();
        protected Object contextResourcesLocker = new Object();

        public DateTime GetDateTimeLatestResourceByTag(string tag)
        {
            DateTime latestDate = DateTime.MinValue;

            lock (contextResourcesLocker)
            {
                Dictionary<string, List<IResource>> dictResources = context.Cache[CacheKeysResources] as Dictionary<string, List<IResource>>;

                // If we have the current tag and photos for it, 
                if (dictResources != null && dictResources.ContainsKey(tag) && dictResources[tag].Count > 0)
                {
                    latestDate = dictResources[tag][0].DownloadedDate;
                }
            }

            return latestDate;
        }


        public void AddResourcesByTag(string tag, List<IResource> listResources)
        {
            lock (contextResourcesLocker)
            {
                Dictionary<string, List<IResource>> dictResources = context.Cache[CacheKeysResources] as Dictionary<string, List<IResource>>;

                if (dictResources == null)
                {
                    return;
                }

                if (!dictResources.ContainsKey(tag))
                {
                    dictResources.Add(tag, new List<IResource>());
                }

                // We don't add again the duplicate resources
                List<IResource> newResources = new List<IResource>();
                foreach (IResource resource in listResources)
                {
                    if (!dictResources[tag].Contains(resource))
                    {
                        newResources.Add(resource);
                    }
                }

                // We check if adding the new photos will result in having more photos than the maximum amount.
                // If so, we remove the extra ones.
                if (newResources.Count > Constants.MAXIMUM_NO_RESOURCES_PER_TAG)
                {
                    newResources.RemoveRange(Constants.MAXIMUM_NO_RESOURCES_PER_TAG, newResources.Count - Constants.MAXIMUM_NO_RESOURCES_PER_TAG);
                }

                int countCurrentSize = Constants.MAXIMUM_NO_RESOURCES_PER_TAG - (dictResources[tag].Count + newResources.Count());

                if (countCurrentSize < 0)
                {
                    countCurrentSize = Math.Abs(countCurrentSize);
                    // TODO check if this is ok
                    dictResources[tag].RemoveRange(Constants.MAXIMUM_NO_RESOURCES_PER_TAG - countCurrentSize, countCurrentSize);
                }

                // Adding at the begining because they are more recent
                dictResources[tag].InsertRange(0, newResources);
            }
        }
        
        public List<IResource> GetResourceByTag(string tag, int results)
        {
            List<IResource> resources = new List<IResource>();

            lock (contextResourcesLocker)
            {
                Dictionary<string, List<IResource>> dictResources = context.Cache[CacheKeysResources] as Dictionary<string, List<IResource>>;
                if (dictResources != null && dictResources.ContainsKey(tag))
                {
                    int noPhotos = Math.Min(dictResources[tag].Count, results);
                    resources.AddRange(dictResources[tag].GetRange(0, noPhotos));
                }
            }

            return resources;
        }

        public bool DeleteResource(string tag, string id)
        {
            lock (contextResourcesLocker)
            {
                Dictionary<string, List<IResource>> dictResources = context.Cache[CacheKeysResources] as Dictionary<string, List<IResource>>;
                if (!dictResources.ContainsKey(tag))
                {
                    return false;
                }

                List<IResource> listResources = dictResources[tag];

                IResource foundResource = null;
                foreach (IResource resource in listResources)
                {
                    if (resource.Id.Equals(id))
                    {
                        foundResource = resource;
                        break;
                    }
                }

                // The photo is not available
                if (foundResource == null)
                {
                    return false;
                }

                dictResources[tag].Remove(foundResource);
            }

            return true;
        }
    }
}